package com.hwl.security.config;

import com.hwl.security.filter.TokenAuthenticationFilter;
import com.hwl.security.filter.TokenLoginFilter;
import com.hwl.security.handler.DefaultPasswordEncoder;
import com.hwl.security.handler.TokenLogoutHandler;
import com.hwl.security.handler.TokenManager;
import com.hwl.security.handler.UnauthorizedEntryPoint;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;

import javax.annotation.Resource;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private UserDetailsService userDetailsService;
    @Resource
    private TokenManager tokenManager;
    @Resource
    private DefaultPasswordEncoder defaultPasswordEncoder;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public void configure(WebSecurity web) throws Exception {
        // "/**"
        web.ignoring().antMatchers("/api/**",
                "/doc.html",
                "/webjars/**",
                "/swagger-resources/**",
                "/v2/api-docs/**"
        );
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling()
                //自定义的未登录处理
                .authenticationEntryPoint(new UnauthorizedEntryPoint()).and()
                //使用JWT，不需要csrf
                .csrf().disable()
                //授权认证，相当于拦截器
                .authorizeRequests()
                //其余请求都要认证
                .anyRequest().authenticated().and()
                .logout().logoutUrl("/admin/acl/index/logout")
                .addLogoutHandler(new TokenLogoutHandler(tokenManager, redisTemplate)).and()
                .addFilter(new TokenLoginFilter(authenticationManager(), tokenManager, redisTemplate))
                .addFilter(new TokenAuthenticationFilter(authenticationManager(), tokenManager, redisTemplate))
                .httpBasic();
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(defaultPasswordEncoder);
    }
}
